function ImageGallery() {
    this.containerElem = $('<div/>');
    addToBody(this.containerElem);
    this.onGalleryCloseEventHandler = function() {};
}

ImageGallery.prototype.onGalleryClose = function (eventHandler) {
    this.onGalleryCloseEventHandler = eventHandler;
};

ImageGallery.prototype.getSliderConfig = function () {
    var me = this;
    return {
        keyboardNavEnabled: true,
        arrows: false,
        arrowsAutoHide: true,
        loop: true,
        controlNavigation: 'non',
        autoScaleSlider: true,
        numImagesToPreload: 2,
        navigateByClick: false,
        globalCaption: true,
        deeplinking: {
            enabled: true,
            change: true,
            prefix: me.currentTag + "-"
        }
    };
};

ImageGallery.prototype.showInitialGallery = function () {
    var hash = window.location.hash;
    if (hash.indexOf("-") > -1) {
        var values = hash.substring(1).split("-");
        var tag = values[0];
        this.loadImagesForTag(tag);
    } else {
        this.loadLatestImages();
    }
};

ImageGallery.prototype.loadImagesForTag = function (tag) {
    var me = this;
    loadImagesForTagAnd(tag, function (images) {
        me.handleLoadImages(images);
    });
};

ImageGallery.prototype.loadLatestImages = function () {
    var me = this;
    loadLatestImagesAnd(function (images) {
        me.handleLoadImages(images);
    });
};

ImageGallery.prototype.setCurrentTag = function (tag) {
    this.currentTag = tag;
};

ImageGallery.prototype.showGallery = function(arrayOfImages) {
    this.galleryElement = $('<div/>');
    this.galleryElement.attr("id", "full-width-slider");
    this.galleryElement.addClass("royalSlider heroSlider rsMinW");

    var me = this;
    arrayOfImages.forEach(function(imageElement) {
        imageElement.appendTo(me.galleryElement);
    });

    this.containerElem.append(this.galleryElement);

    var sliderConfig = this.getSliderConfig();
    this.galleryElement.royalSlider(sliderConfig);

    this.royalSlider = this.galleryElement.data("royalSlider");
    this.royalSlider.ev.on('rsExitFullscreen', function () {
        me.waitForRSToResizeThenClose();
    });
    this.royalSlider.ev.on('rsEnterFullscreen', function () {
        var find = me.containerElem.find('.royalSlider');
        var closeButton = me.createCloseButton();
        $(find[0]).prepend(closeButton);
    });
    this.royalSlider.enterFullscreen();
};

ImageGallery.prototype.handleLoadImages = function (images) {
    if (images.length == 0) {
        log("No images present.");
        return;
    }
    var image = images.peek();
    var tag = image.tags.peek();
    this.setCurrentTag(tag);

    this.imageArray = [];
    var imageElements = [];
    var me = this;
    images.forEach(function (image, index) {
        image.index = index;
        if ( ! image.hidden) {
            me.addImage(image);
            var imageElem = me.createImageElement(image);
            imageElements.push(imageElem);
        }
    });

    this.showGallery(imageElements);
};

ImageGallery.prototype.createCloseButton = function() {
    var closeButton = $('<span/>');
    closeButton.addClass("closeButton");
    var me = this;
    closeButton.click(function() {
        me.closeGallery();
    });

    return closeButton;
};

ImageGallery.prototype.waitForRSToResizeThenClose = function () {
    var me = this;
    setTimeout(function () {
        me.closeGallery();
    }, 100);
};

ImageGallery.prototype.closeGallery = function () {
    var css = {
        visibility: 'visible',
        opacity: 0
    };
    css[this.royalSlider._vendorPref + 'transition'] = 'opacity 400ms ease-in-out';
    this.galleryElement.css(css);

    this.onGalleryCloseEventHandler();

    var me = this;
    setTimeout(function() { me.destroyGallery(); }, 500);
};

ImageGallery.prototype.destroyGallery = function() {
    this.royalSlider.destroy();
    this.containerElem.empty();
    this.royalSlider = null;
    this.galleryElement = null;
};

ImageGallery.prototype.addImage = function (image) {
    calculateImageProperties(image);
    if (this.imageArray.length > 0) {
        image.previous = this.imageArray.peek();
        image.previous.next = image;
    }
    this.imageArray.push(image);
};

ImageGallery.prototype.createImageElement = function (image) {
    var imageContainerElem = $('<div/>');
    imageContainerElem.addClass("rsContent");

    var imageHashElem = $('<span/>');
    imageHashElem.addClass("rsImgHash hidden");
    imageHashElem.text(image.id);
    imageContainerElem.append(imageHashElem);

    var imageLink = $('<a/>');
    imageLink.addClass("rsImg");
    //imageLink.attr("data-rsTmb", image.grayscaleThumbnailSrc);
    imageLink.attr("href", image.imageFile.src);
    imageContainerElem.append(imageLink);

    var caption = this.createImageCaption(image);
    imageContainerElem.append(caption);
    image.thumbnailDiv = imageContainerElem;

    return imageContainerElem;
};

ImageGallery.prototype.findImageById = function (id) {
    return this.images.find(function (image) {
        return image.id == id;
    });
};

ImageGallery.prototype.createImageCaption = function (image) {
    var caption = $('<span/>');
    caption.addClass("caption rsCaption");

    caption.append($('<span class="siteTitle text">daveclay.com/art</span><br/>'));
    var nameElement = $('<span/>');
    nameElement.addClass("imageName");
    nameElement.text(image.name);
    caption.append(nameElement);

    caption.append($("<span> / </span>"));

    var dateElement = $('<span/>');
    dateElement.addClass("imageDate");
    dateElement.text(image.dateText);
    caption.append(dateElement);

    var properties = image.properties;
    if (properties) {
        if (properties["info"]) {
            var infoElement = $('<span/>');
            infoElement.addClass("imageInfo");
            infoElement.text(properties["info"]);
            caption.append($("<br/>"));
            caption.append(infoElement);
        }
    }

    return caption;
};
